#include "myutil_filepath.h"
#include <assert.h>

#ifdef _WIN32
#include <Windows.h>
#endif

using namespace std;

namespace myutil {

    //static const char kEndChar = '\0';
    static const char kFilePathSeparators[] = "\\/";
    static const char kFilePathCurrentDirectory[] = ".";
    static const char kFilePathParentDirectory[] = "..";
    static const char kFilePathExtensionSeparator = '.';

    static const wchar_t kFilePathSeparatorsW[] = L"\\/";
    static const wchar_t kFilePathCurrentDirectoryW[] = L".";
    static const wchar_t kFilePathParentDirectoryW[] = L"..";
    static const wchar_t kFilePathExtensionSeparatorW = L'.';

    template<typename _Ty>
    bool _is_filepath_separator(const _Ty separator)
    {
        size_t len = sizeof(kFilePathSeparators) / sizeof(char);
        for (size_t i = 0; i < len; i++)
        {
            if (separator == kFilePathSeparators[i])
                return true;
        }

        return false;
    }

    template<typename _Ty>
    _Ty filepath_extension(const _Ty& filepath)
    {
        if (filepath.size() == 0)
            return _Ty();
        size_t pos = _Ty::npos;
        if constexpr (std::is_same<_Ty, std::string>())
            pos = filepath.rfind(kFilePathExtensionSeparator);
        else if constexpr (std::is_same<_Ty, std::wstring>())
            pos = filepath.rfind(kFilePathExtensionSeparatorW);
        if (pos == _Ty::npos)
            return _Ty();
        return filepath.substr(pos, _Ty::npos);
    }

    template<typename _Ty>
    _Ty filepath_apart_directory(const _Ty& filepath)
    {
        using char_type = typename string::value_type;
        size_t index = filepath.size() - 1;
        if (index <= 0 || filepath.size() == 0)
            return _Ty();
        _Ty dir;
        for (; index != 0; index--){
            if (_is_filepath_separator<char_type>(filepath[index])){
                if (index == filepath.size() - 1) {
                    dir = filepath;
                }  
                else {
                    dir = filepath.substr(0, index + 1);
                }    
                break;
            }
        }
        return dir;
    }

    // Get the filename from the whole filepath
    template<typename _Ty>
    _Ty filepath_apart_filename(const _Ty& filepath)
    {
        size_t index = filepath.size() - 1;
        if (index <= 0 || filepath.size() == 0)
            return _Ty();
        _Ty filename;
        for (; index != 0; index--){
            if (_is_filepath_separator(filepath[index])){
                if (index != filepath.size() - 1) {
                    filename = filepath.substr(index + 1, _Ty::npos);
                }   
                break;
            }
        }
        return filename;
    }

    std::wstring get_app_dir() {
#ifdef _WIN32
        TCHAR chFileName[MAX_PATH + 1] = { 0 };
        ::GetModuleFileName(GetModuleHandle(NULL), chFileName, MAX_PATH);
        wstring sInstancePath = chFileName;
        int pos = sInstancePath.rfind(L'\\');
        if (pos >= 0)
            sInstancePath = sInstancePath.substr(0, pos + 1);
        else
            sInstancePath = L"";
        return sInstancePath;
#else
        assert(0);
        return L"";
#endif
    }

    void CompileTemplateMyutilFilePath() {
        wstring sFilePath;
        string filepath;
        filepath_extension<std::string>(filepath);
        filepath_extension<std::wstring>(sFilePath);
        filepath_apart_directory<std::string>(filepath);
        filepath_apart_directory<std::wstring>(sFilePath);
        filepath_apart_filename<std::string>(filepath);
        filepath_apart_filename<std::wstring>(sFilePath);
    }


}   //myutil


